/*------------------------------------------------------------------------------
 *  SObject - Base class for all major schematic objects.  
 *  
 *  August 2009, Forhad Ahmed
 *------------------------------------------------------------------------------
 */

package schematic;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.util.Vector;

public class SObject {
    /*
     * Constructor
     */
    public SObject() {
        /*
         * Allocate the object id based on the id-allocation algorithm
         */
        id = id();
        aloc++;
        
        /*
         * initialize the rest of the objects
         */
        init();
    }
    
    
    /*
     * Constructor that explicitly sets the object id (used for creating copies)
     */
    public SObject(int i) {
        id = i;
        aloc++;
        
        init();
    }

    
    /*
     * Initialize the data structures
     */
    public void init() {
        color = null;
        hpoint = new Point();
        spoint = new Point();
        hit_context = new Point();
        move_context = null;
        box  = new Rectangle();
        com = new Point2D.Float();
        dependents = new Vector();
        d = new Point();
        aa = true;   
    }
    
    
    /*
     * Returns a unique id to be assigned to the object.
     */
    public static int id() {
        int r;
        if (monotonic == 0) {
            if (last_free != -1) {
                r = last_free;
                last_free = -1;
            } else {
                r = oid++;
            }
        } else {
            r = oid++;
        }
        return r;
    }

    
    /*
     * Called when the object is freed. The id is deallocated so other objects
     * can use that id.
     */
    public void finalize() {
        free++;
        if (checkpoint == -2) System.out.println("FREE: " + this);
        last_free = this.id;
    }

    
    /*
     * Return a copy of the object to be used for checkpointing
     */
    public SObject checkpoint(int action) {
        return this;
    }
    
    
    /*
     * Used for the 'uncheckpoint' operation.  Given a checkpointed object, 
     * revert this original/modified object to the checkpointed object
     */
    public void revert(SObject checkpoint) {
        
    }
    

    /*
     * Virtual draw method. Canvas is passed in so that screen coordinates can
     * be derived from canvas coordinates that are stored in the object.
     */
    public void draw(Graphics g, Schematic c) {

    }

    
    /*
     * Given a screen point, figure out if the object has been "hit" or not by
     * that point.
     */
    public boolean hit(int sx, int sy) {
        return false;
    }

    
    /*
     * Set the hit offset for this canvas object. 
     */
    public void setHitContext(int cx, int cy) {
        
    }
    
    
    /*
     * Before a leader is moved, set the context in which the move happens.
     * (usually the context is the list of objects that are selected when the
     * move is happening)
     */
    public void setMoveContext(Object ctx) {
         
    }
    
    
    /*
     * Given a screen point, figure out which object (if any) has been hovered
     * over. This hovered-over object is called a "suggestion" because it will
     * be suggested to the canvas for edge properties.
     */
    public SObject suggest(int sx, int sy) {
        return null;
    }


    /*
     * Get the objects that are "dependent" on this object.
     */
    public Vector dependents() {
        return null;
    }
    
    
    /*
     * Given a parent object, and some offset, move this object in response to 
     * the parent object moving by the given offset.  It's assumed that this 
     * object is a dependent of the parent object. 
     */
    public void subordinateMove(SObject p, int dx, int dy) {
        
    }
    
    
    /*
     * When a parent object moves, some child objects have to move in response.
     * This function saves the state of the child object right before the parent
     * is moved so that the state can be used when it comes to moving the child.
     */
    public void saveMoveState(SObject parent) {
        
    }
    
    
    /*
     * Place the object at x, y.  Return the delta for the move if object is a
     * leader-capable object.
     */
    public Point place(int x, int y) {
        return null;
    }
    
    
    /*
     * Translate the object by dx, dy
     */
    public void move(int dx, int dy) {
        
    }

    
    /*
     * Rotate the object by (dir * pi/2) from its current orientaiton
     */
    public void rotate(int dir) {
        
    }
    
    
    /*
     * Rotate the object by pi/2 from its current orientation.  Use the point
     * as the center for the rotation.
     */
    public void rotate(int dir, int x, int y) {
        
    }
    
    
    /*
     * 
     */
    public void flip(int orientation, int axis) {
        
    }
    
    
    /*
     * Get the bounding box for this object in canvas coordinates
     */
    public Rectangle getBoundingBox() {
        return null;
    }

    
    /*
     * Return whether this object is selectable by the selection box or not
     */
    public boolean selectable() {
        return true;
    }
    
    
    /*
     * 
     */
    public boolean deletable() {
        return true;
    }
    
    
    /*
     * Given an original/modified object, calculate the difference and save it
     * in 'this' checkpointed object and use 'this' as part of the diff vector
     */
    public SObject diff(SObject object) {
        return null;
    }
    
    
    /*
     * Reverse patch a diff object (undo)
     */
    public void rpatch(SObject object, Schematic schematic) {
        
    }
    
    
    /*
     * Forward patch a diff object (redo)
     */
    public void patch(SObject object, Schematic schematic) {
        
    }
    
    
    /*
     * Find the center of mass point for this object
     */
    public Point2D.Float center() {
        return null;
    }

    
    /*
     * Return the type string (sub-type of VCanvasObject) for this object
     */
    public String typeString() {
        return null;
    }
    
    
    /*
     * Return a complete dump of the object including it's linkage
     */
    public String dump() {
        return null;
    }

    
    /*
     * Stringify the object
     */
    public String toString() {
        return Integer.toString(id) + " " + typeString() + 
               (checkpoint == Schematic.CHECKPOINT_ORIGINAL ? 
               "" : " [copy] ");
    }

    
    /*
     * Some common fields for all VCanvasObjects:
     * 
     * id       - uniquely allocated id for this object; 
     * selected - is this object selected on canvas? 
     * aa       - anti-aliasing
     * color    - color for drawing this object
     * hpoint   - temporary point object used for calculating hit point
     * spoint   - temporary point object used for calculating suggest point 
     * box      - temporary rectangle to calculate bounding box
     * d        - temporary point to calculate move delta
     */
    public int       id;
    public boolean   mark_selected = false;
    public boolean   selected = false;
    public boolean   mark_deleted = false;
    public boolean   aa = false;
    public Color     color;
    public Point     hpoint;
    public Point     spoint;
    public Point     hit_context;
    public Object    move_context;
    public Vector    dependents;
    public Rectangle box;
    public Point     d;

    public Point2D.Float com;
    
    /*
     * Static fields for id allocation purposes
     * 
     * oid  - current id pointer to allocate from 
     * free - last freed id to be picked up for new allocation
     */
    public static int monotonic = 1;
    public static int oid = 0;
    public static int last_free = -1;
    public static int aloc = 0;
    public static int free = 0;

    /*
     * checkpoint - Integer used to represent the checkpoint state (MOD/ADD/DEL) 
     *              of an object if the object is a checkpointed object. 
     *              Otherwise, the value is meaning-less
     * original   - Pointer to the original object that's in the canvas.
     */
    protected int     checkpoint = Schematic.CHECKPOINT_ORIGINAL;
    protected SObject original = null;

}
